home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / pgp23src.zip / SYSTEM.C < prev    next >
C/C++ Source or Header  |  1993-05-09  |  39KB  |  1,772 lines

  1. /*
  2.  * system.c
  3.  *
  4.  * Routines specific for non-MSDOS implementations of pgp.
  5.  * 
  6.  *    Modified 24-Jun-92 HAJK
  7.  *    Adapt for VAX/VMS.
  8.  *
  9.  *    Modified: 11-Nov-92 HAJK
  10.  *    Add FDL Support Routines. 
  11.  *
  12.  *    Modified: 31-Jan-93 HAJK
  13.  *    Misc. updates for terminal handling.
  14.  *    Add VMS command stuff.
  15.  *    Add fileparse routine.
  16.  */
  17. #include <stdio.h>
  18. #include "exitpgp.h"
  19. #include "system.h"
  20. #include "usuals.h"
  21.  
  22. /*===========================================================================*/
  23. /*
  24.  * UNIX
  25.  */
  26.  
  27. #ifdef UNIX
  28. /*
  29.  * Define USE_SELECT to use the select() system call to check if
  30.  * keyboard input is available. Define USE_NBIO to use non-blocking
  31.  * read(). If you don't define anything the FIONREAD ioctl() command
  32.  * will be used.
  33.  *
  34.  * Define NOTERMIO if you don't have the termios stuff
  35.  */
  36. #include <sys/types.h>
  37. #include <fcntl.h>
  38.  
  39. #ifndef    NOTERMIO
  40. #ifndef SVR2
  41. #include <termios.h>
  42. #else
  43. #include <termio.h>
  44. #endif /* not SVR2 */
  45. #else
  46. #include <sgtty.h>
  47. #endif
  48.  
  49. #ifdef    USE_SELECT
  50. #include <sys/time.h>
  51. #ifdef _IBMR2
  52. #include <sys/select.h>
  53. #endif /* _IBMR2 */
  54. #else
  55. #ifndef USE_NBIO
  56. #ifndef sun
  57. #include <sys/ioctl.h>        /* for FIONREAD */
  58. #else /* including both ioctl.h and termios.h gives a lot of warnings on sun */
  59. #include <sys/filio.h>
  60. #endif /* sun */
  61. #ifndef FIONREAD
  62. #define    FIONREAD    TIOCINQ
  63. #endif
  64. #endif
  65. #endif
  66. #include <signal.h>
  67.  
  68. static void setsigs(void);
  69. static void rmsigs(void);
  70. static void sig1(int);
  71. static void sig2(int);
  72. void breakHandler(int);
  73. static int ttyfd= -1;
  74. #ifndef SVR2
  75. static void (*savesig)(int);
  76. #else
  77. static int (*savesig)(int);
  78. #endif
  79.  
  80. void ttycbreak(void);
  81. void ttynorm(void);
  82.  
  83. #ifndef NEED_KBHIT
  84. #undef USE_NBIO
  85. #endif
  86.  
  87. #ifndef NOTERMIO
  88. #ifndef SVR2
  89. static struct termios itio, tio;
  90. #else
  91. static struct termio itio, tio;
  92. #endif /* not SVR2 */
  93. #else
  94. static struct sgttyb isg, sg;
  95. #endif
  96.  
  97. #ifdef USE_NBIO
  98. static int kbuf= -1;    /* buffer to store char read by kbhit() */
  99. static int fflags;
  100. #endif
  101.  
  102. static int gottio = 0;
  103.  
  104. void ttycbreak(void)
  105. {
  106.     if (ttyfd == -1) {
  107.         if ((ttyfd = open("/dev/tty", O_RDWR)) < 0) {
  108.             fprintf(stderr, "cannot open tty, using stdin\n");
  109.             ttyfd = 0;
  110.         }
  111.     }
  112. #ifndef NOTERMIO
  113. #ifndef SVR2
  114.     if (tcgetattr(ttyfd, &tio) < 0)
  115. #else
  116.     if (ioctl(ttyfd, TCGETA, &tio) < 0)
  117. #endif  /* not SVR2 */
  118.     {    fprintf (stderr, "\nUnable to get terminal characteristics: ");
  119.         perror("ioctl");
  120.         exitPGP(1);
  121.     }
  122.     itio = tio;
  123.     setsigs();
  124.     gottio = 1;
  125. #ifdef USE_NBIO
  126.     tio.c_cc[VMIN] = 0;
  127. #else
  128.     tio.c_cc[VMIN] = 1;
  129. #endif
  130.     tio.c_cc[VTIME] = 0;
  131.     tio.c_lflag &= ~(ECHO|ICANON);
  132. #ifndef SVR2
  133.     tcsetattr (ttyfd, TCSAFLUSH, &tio);
  134. #else
  135.     ioctl(ttyfd, TCSETAF, &tio);
  136. #endif /* not SVR2 */
  137. #else
  138.     if (ioctl(ttyfd, TIOCGETP, &sg) < 0)
  139.     {    fprintf (stderr, "\nUnable to get terminal characteristics: ");
  140.         perror("ioctl");
  141.         exitPGP(1);
  142.     }
  143.     isg = sg;
  144.     setsigs();
  145.     gottio = 1;
  146. #ifdef CBREAK
  147.     sg.sg_flags |= CBREAK;
  148. #else
  149.     sg.sg_flags |= RAW;
  150. #endif
  151.     sg.sg_flags &= ~ECHO;
  152.     ioctl(ttyfd, TIOCSETP, &sg);
  153. #endif    /* !NOTERMIO */
  154. #ifdef USE_NBIO
  155. #ifndef O_NDELAY
  156. #define    O_NDELAY    O_NONBLOCK
  157. #endif
  158.     if ((fflags = fcntl(ttyfd, F_GETFL, 0)) != -1)
  159.         fcntl(ttyfd, F_SETFL, fflags|O_NDELAY);
  160. #endif
  161. }
  162.  
  163.  
  164. void ttynorm(void)
  165. {    gottio = 0;
  166. #ifdef USE_NBIO
  167.     if (fcntl(ttyfd, F_SETFL, fflags) == -1)
  168.         perror("fcntl");
  169. #endif
  170. #ifndef NOTERMIO
  171. #ifndef SVR2
  172.     tcsetattr (ttyfd, TCSAFLUSH, &itio);
  173. #else
  174.     ioctl(ttyfd, TCSETAF, &itio);
  175. #endif /* not SVR2 */
  176. #else
  177.     ioctl(ttyfd, TIOCSETP, &isg);
  178. #endif
  179.     rmsigs();
  180. }
  181.  
  182. static void sig1 (int sig)
  183. {
  184. #ifndef NOTERMIO
  185. #ifndef SVR2
  186.     tcsetattr (ttyfd, TCSANOW, &itio);
  187. #else
  188.     ioctl(ttyfd, TCSETAW, &itio);
  189. #endif /* not SVR2 */
  190. #else
  191.     ioctl(ttyfd, TIOCSETP, &isg);
  192. #endif
  193.     signal (sig, SIG_DFL);
  194.     if (sig == SIGINT)
  195.         breakHandler(SIGINT);
  196.     kill (getpid(), sig);
  197. }
  198.  
  199. static void sig2 (int sig)
  200. {    if (gottio)
  201.         ttycbreak();
  202.     else
  203.         setsigs();
  204. }
  205.  
  206. static void setsigs(void)
  207. {    savesig = signal (SIGINT, sig1);
  208. #ifdef    SIGTSTP
  209.     signal (SIGCONT, sig2);
  210.     signal (SIGTSTP, sig1);
  211. #endif
  212. }
  213.  
  214. static void rmsigs(void)
  215. {    signal (SIGINT, savesig);
  216. #ifdef    SIGTSTP
  217.     signal (SIGCONT, SIG_DFL);
  218.     signal (SIGTSTP, SIG_DFL);
  219. #endif
  220. }
  221.  
  222. #ifdef NEED_KBHIT
  223. #ifndef CRUDE
  224. int kbhit(void)
  225. /* Return TRUE if there is a key to be read */
  226. {
  227. #ifdef USE_SELECT        /* use select() system call */
  228.     struct timeval t;
  229.     fd_set n;
  230.     int r;
  231.  
  232.     timerclear(&t);
  233.     FD_ZERO(&n);
  234.     FD_SET(ttyfd, &n);
  235.     r = select(32, &n, NULL, NULL, &t);
  236.     if (r == -1) {
  237.         perror("select");
  238.         exitPGP(1);
  239.     }
  240.     return r > 0;
  241. #else
  242. #ifdef    USE_NBIO        /* use non-blocking read() */
  243.     unsigned char ch;
  244.     if (kbuf >= 0) 
  245.         return(1);
  246.     if (read(ttyfd, &ch, 1) == 1) {
  247.         kbuf = ch;
  248.         return(1);
  249.     }
  250.     return(0);
  251. #else
  252.     long lf;
  253.     if (ioctl(ttyfd, FIONREAD, &lf) == -1) {
  254.         perror("ioctl: FIONREAD");
  255.         exitPGP(1);
  256.     }
  257.     return(lf);
  258. #endif
  259. #endif
  260. }
  261. #endif    /* !CRUDE */
  262. #endif
  263.  
  264. int getch(void)
  265. {
  266.     char c;
  267. #ifdef USE_NBIO
  268.     while (!kbhit());    /* kbhit() does the reading */
  269.     c = kbuf;
  270.     kbuf = -1;
  271. #else
  272.     read(ttyfd, &c, 1);
  273. #endif
  274.     return(c);
  275. }
  276.  
  277. #if defined(_BSD) && !defined(__STDC__)
  278.  
  279. VOID *memset(s, c, n)
  280. VOID *s;
  281. register int c, n;
  282. {
  283.     register char *p = s;
  284.     ++n;
  285.     while (--n)
  286.         *p++ = c;
  287.     return(s);
  288. }
  289. int memcmp(s1, s2, n)
  290. register unsigned char *s1, *s2;
  291. register int n;
  292. {
  293.     if (!n)
  294.         return(0);
  295.     while (--n && *s1 == *s2) {
  296.         ++s1;
  297.         ++s2;
  298.     }
  299.     return(*s1 - *s2);
  300. }
  301. VOID *memcpy(s1, s2, n)
  302. register char *s1, *s2;
  303. register int n;
  304. {
  305.     char *p = s1;
  306.     ++n;
  307.     while (--n)
  308.         *s1++ = *s2++;
  309.     return(p);
  310. }
  311. #endif /* _BSD */
  312.  
  313. #if (defined(MACH) || defined(SVR2) || defined(_BSD)) && !defined(NEXT)
  314. int remove(name)
  315. char *name;
  316. {
  317.     return unlink(name);
  318. }
  319. #endif
  320.  
  321. #ifdef SVR2
  322. int rename(old, new)
  323. register char *old, *new;
  324. {
  325.     unlink(new);
  326.     if (link(old, new) < 0)
  327.         return -1;
  328.     if (unlink(old) < 0) {
  329.         unlink(new);
  330.         return -1;
  331.     }
  332.     return 0;
  333. }
  334. #endif /* SVR2 */
  335.  
  336. /* not all unices have clock() */
  337. long
  338. Clock()    /* not a replacement for clock(), just for random number generation */
  339. {
  340. #if defined(_BSD) || defined(sun) || defined(MACH) || defined(linux)
  341. #include <sys/time.h>
  342. #include <sys/resource.h>
  343.     struct rusage ru;
  344.  
  345.     getrusage(RUSAGE_SELF, &ru);
  346.     return ru.ru_utime.tv_sec + ru.ru_utime.tv_usec +
  347.         ru.ru_stime.tv_sec + ru.ru_stime.tv_usec +
  348.         ru.ru_minflt + ru.ru_majflt +
  349.         ru.ru_inblock + ru.ru_oublock +
  350.         ru.ru_maxrss + ru.ru_nvcsw + ru.ru_nivcsw;
  351.  
  352. #else    /* no getrusage() */
  353. #include <sys/times.h>
  354.     struct tms tms;
  355.  
  356.     times(&tms);
  357.     return(tms.tms_utime + tms.tms_stime);
  358. #endif
  359. }
  360. #endif /* UNIX */
  361.  
  362.  
  363. /*===========================================================================*/
  364. /*
  365.  * VMS
  366.  */
  367.  
  368. #ifdef VMS            /* kbhit()/getch() equivalent */
  369.  
  370. /*
  371.  * This code defines an equivalent version of kbhit() and getch() for
  372.  * use under VAX/VMS, together with an exit handler to reset terminal
  373.  * characteristics.
  374.  *
  375.  * This code assumes that kbhit() has been invoked to test that there
  376.  * are characters in the typeahead buffer before getch() is invoked to
  377.  * get the answer.
  378.  */
  379.  
  380. #include <signal.h>
  381. #include <string.h>
  382. #include <file.h>
  383. #include <ctype.h>
  384. #include "pgp.h"
  385. #include "mpilib.h"
  386. #include "mpiio.h"
  387. #include "fileio.h"
  388. extern byte textbuf[DISKBUFSIZE];   /*    Defined in FILEIO.C */
  389.  
  390. /*      
  391. **  VMS Private Macros
  392. */      
  393. #include <descrip.h>
  394. #include <devdef>
  395. #include <iodef.h>
  396. #include <ttdef.h>
  397. #include <tt2def.h>
  398. #include <dcdef.h>
  399. #include <climsgdef.h>
  400. #include <rms.h>
  401. #include <hlpdef.h>
  402.  
  403. #define MAX_CMDSIZ    256  /*  Maximum command size */
  404. #define MAX_FILENM    255 /* Mamimum file name size */
  405.  
  406. #define FDL$M_FDL_STRING    2        /* Use string for fdl text */
  407. #define FDLSIZE            4096    /* Maximum possible file size */
  408.  
  409. #ifdef _USEDCL_
  410.  
  411. /*
  412.  * Declare some external procedure prototypes (saves me confusion!)
  413.  */
  414. extern int lib$get_input(
  415.         struct dsc$descriptor *resultant,
  416.         struct dsc$descriptor *prompt, 
  417.         unsigned short *resultant_length);
  418. extern int lib$put_output(
  419.         struct dsc$descriptor *output);
  420. extern int lib$sig_to_ret();
  421. /*      
  422. **  The CLI routines are documented in the system routines manual.
  423. */      
  424. extern int cli$dcl_parse(
  425.         struct dsc$descriptor *command,
  426.         char cmd_table[],
  427.         int (*get_command)(
  428.         struct dsc$descriptor *resultant,
  429.         struct dsc$descriptor *prompt, 
  430.         unsigned short *resultant_length),
  431.         int (*get_parameter)(
  432.         struct dsc$descriptor *resultant,
  433.         struct dsc$descriptor *prompt, 
  434.         unsigned short *resultant_length),
  435.         struct dsc$descriptor *prompt);
  436. extern int cli$present( struct dsc$descriptor *object);
  437. extern int cli$_get_value(
  438.         struct dsc$descriptor *object,
  439.         struct dsc$decsriptor *value,
  440.         unsigned short *value_len);
  441. /*
  442.  * Static Data
  443.  */
  444. static $DESCRIPTOR (cmdprmt_d, "DROPSAFE> ");  /*  Prompt string */
  445.  
  446. #endif _USEDCL_
  447.  
  448. static volatile short    _kbhitChan_ = 0;
  449.  
  450. static volatile struct IOSB {
  451.     unsigned short sts;
  452.     unsigned short byteCount;
  453.     unsigned short terminator;
  454.     unsigned short terminatorSize;
  455.     } iosb;
  456.  
  457. static $DESCRIPTOR (kbdev_desc, "SYS$COMMAND:");
  458.  
  459. static volatile struct {
  460.     char Class;
  461.     char Type;
  462.     unsigned short BufferSize;
  463.     unsigned int Mode;
  464.     int ExtChar;
  465.   } CharBuf, OldCharBuf;
  466.  
  467. static $DESCRIPTOR (out_file_descr, "SYS$DISK:[]"); /* Default Output File Descr */
  468.  
  469. static int flags = FDL$M_FDL_STRING;
  470.  
  471. /*
  472.  * **-kbhit_handler-This exit handler restores the terminal characteristics
  473.  *
  474.  * Description:
  475.  *
  476.  * This procedure is invoked to return the the terminal to normality (depends
  477.  * on what you think is normal!). Anyway, it gets called to restore
  478.  * characteristics either through ttynorm or via an exit handler.
  479.  */
  480. static void kbhit_handler(int *sts)
  481. {
  482.   ttynorm();
  483.   (void) sys$dassgn (
  484.       _kbhitChan_);
  485.   _kbhitChan_ = 0;
  486. }
  487.  
  488. /*
  489.  * Data Structures For Linking Up Exit Handler 
  490.  */
  491. unsigned int exsts;
  492.  
  493. static struct {
  494.     int link;
  495.     VOID *rtn;
  496.     int argcnt;
  497.     int *stsaddr;
  498.    } exhblk = { 0, &(kbhit_handler), 1, &(exsts)};
  499. /*
  500.  * **-kbhit_Getchn-Get Channel
  501.  *
  502.  * Functional Description:
  503.  *
  504.  * Private routine to get a terminal channel and save the terminal
  505.  * characteristics.
  506.  *
  507.  * Arguments:
  508.  *
  509.  *  None.
  510.  *
  511.  * Returns:
  512.  *
  513.  *  If 0, channel already assigned. If odd, then assign was successful
  514.  * otherwise returns VMS error status.
  515.  *
  516.  * Implicit Inputs:
  517.  *
  518.  * _kbhitChan_    Channel assigned to the terminal (if any).
  519.  *
  520.  * Implicit Outputs:
  521.  *
  522.  *  OldCharBuf    Initial terminal characteristics.
  523.  *  _kbhitChan_    Channel assigned to the terminal.
  524.  *
  525.  * Side Effects:
  526.  *
  527.  *  Establishes an exit handler to restore characteristics and deassign
  528.  * terminal channel.
  529.  */
  530. static int kbhit_Getchn()
  531. {
  532.     int sts = 0;
  533.  
  534.     if (_kbhitChan_ == 0) {
  535.     if ((sts = sys$assign (
  536.                &kbdev_desc,
  537.                &_kbhitChan_,
  538.                0,
  539.                0)) & 1) {
  540.         if ((sts = sys$qiow (
  541.                    0,
  542.                    _kbhitChan_,
  543.                    IO$_SENSEMODE,
  544.                    &iosb,
  545.                    0,
  546.                    0,
  547.                    &OldCharBuf,
  548.                    12,
  549.                    0,
  550.                    0,
  551.                    0,
  552.                    0)) & 01) sts = iosb.sts;
  553.         if (sts & 01) {
  554.           if (!(OldCharBuf.Class & DC$_TERM)) {
  555.         fprintf(stderr,"\nNot running on a terminal");
  556.         exitPGP(1);
  557.           }
  558.           (void) sys$dclexh (&exhblk);
  559.         }
  560.     }
  561.     }
  562.     return(sts);
  563. }
  564. /*      
  565.  * **-ttynorm-Restore initial terminal characteristics
  566.  *
  567.  * Functional Description:
  568.  *
  569.  * This procedure is invoked to restore the initial terminal characteristics.
  570.  */
  571. void ttynorm()
  572. /*
  573.  * Arguments:
  574.  *
  575.  *  None.
  576.  *
  577.  * Implicit Inputs:
  578.  *
  579.  *  OldCharBuf    Initial terminal characteristics.
  580.  *  _kbhitChan_    Channel assigned to the terminal.
  581.  *
  582.  * Implicit Outputs:
  583.  *
  584.  *  None.
  585.  */      
  586. {
  587.   int sts;
  588.  
  589.   if (_kbhitChan_ != 0) {
  590.       CharBuf.Mode = OldCharBuf.Mode;
  591.       CharBuf.ExtChar = OldCharBuf.ExtChar;
  592.     /*
  593.       CharBuf.Mode &= ~TT$M_NOECHO;
  594.       CharBuf.ExtChar &= ~TT2$M_PASTHRU;
  595.     */
  596.       if ((sts = sys$qiow (
  597.                    0,
  598.                    _kbhitChan_,
  599.                    IO$_SETMODE,
  600.                    &iosb,
  601.                    0,
  602.                    0,
  603.                    &OldCharBuf,
  604.                    12,
  605.                    0,
  606.                    0,
  607.                    0,
  608.                    0)) & 01) sts = iosb.sts;
  609.       if (!(sts & 01)) {
  610.         fprintf(stderr,"\nFailed to reset terminal characteristics!");
  611.         (void) lib$signal(sts);
  612.       }
  613.    }
  614.    return;
  615. }
  616. /*
  617.  * **-kbhit-Find out if a key has been pressed
  618.  *
  619.  * Description:
  620.  *
  621.  * Make the terminal noecho and sense the characters coming in by looking at
  622.  * the typeahead count. Note that the character remains in the typeahead buffer
  623.  * untill either read, or that the user types a Control-X when not in 'passall'
  624.  * mode.
  625.  */
  626. int kbhit()
  627. /*
  628.  * Arguments:
  629.  *
  630.  *  None.
  631.  *
  632.  * Returns:
  633.  *
  634.  *  TRUE  if there is a character in the typeahead buffer.
  635.  *  FALSE if there is no character in the typeahead buffer.
  636.  */
  637.  
  638.  
  639. {
  640.   int sts;
  641.  
  642.   struct {
  643.     unsigned short TypAhdCnt;
  644.     char FirstChar;
  645.     char Reserved[5];
  646.   } TypCharBuf;
  647.  
  648.   /*
  649.   **  Get typeahead count
  650.   */
  651.   if ((sts = sys$qiow (
  652.                0,
  653.                _kbhitChan_,
  654.                IO$_SENSEMODE | IO$M_TYPEAHDCNT,
  655.                &iosb,
  656.                0,
  657.                0,
  658.                &TypCharBuf,
  659.                8,
  660.                0,
  661.                0,
  662.                0,
  663.                0)) & 01) sts = iosb.sts;
  664.   if (sts & 01) return(TypCharBuf.TypAhdCnt>0);
  665.   (void) lib$signal(sts);
  666.   exitPGP(1);
  667. }
  668.  
  669. static int NoTerm[2] = { 0, 0};  /*  TT Terminator Mask (Nothing) */
  670.  
  671. /*
  672.  * **-getch-Get a character and return it
  673.  *
  674.  * Description:
  675.  *
  676.  * Get a character from the keyboard and return it. Unlike Unix, the character
  677.  * will be explicitly echoed unless ttycbreak() has been called first. If the
  678.  * character is in the typeahead, that will be read first.
  679.  */
  680. int getch()
  681. /*
  682.  * Arguments:
  683.  *
  684.  *  None.
  685.  *
  686.  * Returns:
  687.  *
  688.  *  Character Read.
  689.  */
  690. {
  691.   unsigned int sts;
  692.   volatile char CharBuf;
  693.  
  694.   if (((sts = kbhit_Getchn()) & 01) || sts == 0) {
  695.       if ((sts = sys$qiow (
  696.                   0,
  697.                   _kbhitChan_,
  698.                   IO$_READVBLK,
  699.                   &iosb,
  700.                   0,
  701.                   0,
  702.                   &CharBuf,
  703.                   1,
  704.                   0,
  705.                   &NoTerm,
  706.                   0,
  707.                   0)) & 01) sts = iosb.sts;
  708.   }
  709.   if (sts & 01) return ((int) CharBuf);
  710.   fprintf(stderr,"\nFailed to get character");
  711.   (void) lib$signal(sts);
  712. }
  713. /*
  714.  * **-putch-Put Character To 'Console' Device
  715.  *
  716.  * This procedure is a companion to getch, outputing a character to the
  717.  * terminal with a minimum of fuss (no VAXCRTLK, no RMS!). This routine
  718.  * simply gets a channel (if there isn't one already and uses QIO to
  719.  * output.
  720.  *
  721.  */
  722. int putch(int chr)
  723. /*
  724.  * Arguments:
  725.  *  chr        Character to output.
  726.  *
  727.  * Returns:
  728.  *
  729.  *  Status return from Getchn and qio.
  730.  *
  731.  * Side Effects
  732.  *
  733.  * May assign a channel to the terminal.
  734.  */
  735. {
  736.   unsigned int sts;
  737.  
  738.   if (((sts = kbhit_Getchn()) & 01) || sts == 0) {
  739.       if ((sts = sys$qiow (
  740.                   0,
  741.                   _kbhitChan_,
  742.                   IO$_WRITEVBLK,
  743.                   &iosb,
  744.                   0,
  745.                   0,
  746.                   &chr,
  747.                   1,
  748.                   0,
  749.                   0,
  750.                   0,
  751.                   0)) & 01) sts = iosb.sts;
  752.   }
  753.   if (sts & 01) return (sts);
  754.   fprintf(stderr,"\nFailed to put character");
  755.   (void) lib$signal(sts);
  756. }
  757. /*
  758.  * **-ttycbreak-Set Unix-like Cbreak mode
  759.  *
  760.  * Functional Description:
  761.  *
  762.  * This code must be invoked to produce the Unix-like cbreak operation which
  763.  * disables echo, allows control character input.
  764.  */
  765. void ttycbreak ()
  766. /*
  767.  * Arguments:
  768.  *
  769.  *  None.
  770.  *
  771.  * Returns:
  772.  *
  773.  *  None.
  774.  *
  775.  * Side Effects
  776.  *
  777.  * May assign a channel to the terminal.
  778.  */
  779. {
  780.     struct {
  781.     unsigned short TypAhdCnt;
  782.     char FirstChar;
  783.     char Reserved[5];
  784.     } TypCharBuf;
  785.     char buf[80];
  786.     int sts;
  787.  
  788.     if (((sts = kbhit_Getchn()) & 01) || sts == 0) {
  789. /*
  790.  * Flush any typeahead before we change characteristics
  791.  */
  792.     if ((sts = sys$qiow (
  793.                    0,
  794.                    _kbhitChan_,
  795.                    IO$_SENSEMODE | IO$M_TYPEAHDCNT,
  796.                    &iosb,
  797.                    0,
  798.                    0,
  799.                    &TypCharBuf,
  800.                    8,
  801.                    0,
  802.                    0,
  803.                    0,
  804.                    0)) & 01) sts = iosb.sts;
  805.     if (sts) {
  806.         if (TypCharBuf.TypAhdCnt>0) {
  807.         if ((sts = sys$qiow (
  808.                 0,
  809.                _kbhitChan_,
  810.                IO$_READVBLK | IO$M_NOECHO | IO$M_TIMED,
  811.                &iosb,
  812.                0,
  813.                0,
  814.                &buf,
  815.                (TypCharBuf.TypAhdCnt >= 80 ? 80 : TypCharBuf.TypAhdCnt),
  816.                1,
  817.                &NoTerm,
  818.                0,
  819.                0)) & 01) sts = iosb.sts;
  820.                
  821.         if (sts)
  822.             TypCharBuf.TypAhdCnt -= iosb.byteCount;
  823.         }
  824.     }
  825.     if (!(sts & 01)) TypCharBuf.TypAhdCnt = 0;
  826. /*
  827.  * Modify characteristics
  828.  */
  829.     CharBuf = OldCharBuf;
  830.     CharBuf.Mode = (OldCharBuf.Mode | TT$M_NOECHO) & ~TT$M_NOTYPEAHD;
  831.     CharBuf.ExtChar = OldCharBuf.ExtChar | TT2$M_PASTHRU;
  832.     if ((sts = sys$qiow (
  833.                0,
  834.                _kbhitChan_,
  835.                IO$_SETMODE,
  836.                &iosb,
  837.                0,
  838.                0,
  839.                &CharBuf,
  840.                12,
  841.                    0,
  842.                0,
  843.                0,
  844.                0)) & 01) sts = iosb.sts;
  845.     if (!(sts & 01)) {
  846.       fprintf(stderr,"\nttybreak()- Failed to set terminal characteristics!");
  847.       (void) lib$signal(sts);
  848.       exitPGP(1);
  849.     }
  850.     }
  851. }
  852.  
  853.  
  854. #ifdef _USEDCL_
  855.  
  856. /*
  857.  * **-vms_getcmd-Get VMS Style Foreign Command
  858.  *
  859.  * Functional Description:
  860.  *
  861.  *  Get command from VAX/VMS foreign command line interface and parse
  862.  * according to DCL rules. If the command line is ok, it can then be
  863.  * parsed according to the rules in the DCL command language table.
  864.  *
  865.  */
  866. int vms_GetCmd( char *cmdtbl)
  867. /*
  868.  * Arguments:
  869.  *
  870.  *  cmdtbl    Pointer to command table to parse.
  871.  *
  872.  * Returns:
  873.  *
  874.  *  ...TBS...
  875.  *
  876.  * Implicit Inputs:
  877.  *
  878.  *  Command language table defined in DROPDCL.CLD
  879.  */
  880. {
  881.     int sts;
  882.     char cmdbuf[MAX_CMDSIZ];
  883.     unsigned short cmdsiz;
  884.     struct dsc$descriptor cmdbuf_d = {0,0,0,0};
  885.     struct dsc$descriptor infile_d = {0,0,0,0};
  886.     char filenm[MAX_FILENM];
  887.     unsigned short filenmsiz;
  888.     unsigned short verb_size;
  889.  
  890.     /*      
  891.     **  DCL Parse Expects A Command Verb Prefixing The Argumnents
  892.     **    fake it!
  893.     */      
  894.     verb_size = cmdprmt_d.dsc$w_length - 2;  /*  Loose '> ' characters */
  895.     cmdbuf_d.dsc$w_length = MAX_CMDSIZ-verb_size-1;
  896.     cmdbuf_d.dsc$a_pointer = strncpy(cmdbuf,cmdprmt_d.dsc$a_pointer,verb_size) +
  897.     verb_size+1;
  898.     cmdbuf[verb_size++]=' ';
  899.     if ((sts = lib$get_foreign (  /*  Recover command line from DCL */
  900.                &cmdbuf_d, 
  901.                0, 
  902.                &cmdsiz, 
  903.                0)) & 01) {
  904.     cmdbuf_d.dsc$a_pointer = cmdbuf;
  905.     cmdbuf_d.dsc$w_length = cmdsiz + verb_size;
  906.     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions to return */
  907.         sts = cli$dcl_parse(  /*  Parse Command Line */
  908.             &cmdbuf_d,
  909.             cmdtbl,            
  910.             lib$get_input,
  911.             lib$get_input,
  912.             &cmdprmt_d);
  913.     }
  914.     return(sts);
  915. }
  916. /*
  917.  * **-vms_TstOpt-Test for command qualifier present
  918.  *
  919.  * Functional Description:
  920.  *
  921.  * This procedure is invoked to test whether an option is present. It is
  922.  * really just a jacket routine for the system routine CLI$PRESENT
  923.  * converting the argument and result into 'C' speak.
  924.  *
  925.  */
  926. vms_TstOpt(char opt)
  927. /*
  928.  * Arguments:
  929.  *
  930.  *  opt        Character label of qualifier to test for.
  931.  *
  932.  * Returns:
  933.  *
  934.  *  +1    Option present.
  935.  *  0    Option absent.
  936.  *  -1    Option negated.
  937.  *
  938.  * Implicit Inputs:
  939.  *
  940.  * Uses DCL command line context established by vms_GetOpt.
  941.  */
  942. {
  943.     int sts;
  944.     char buf;
  945.     struct dsc$descriptor option_d = { 1, 0, 0, &buf};
  946.  
  947.     buf = _toupper(opt);
  948.     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions to return */
  949.     switch (sts=cli$present(&option_d))
  950.     {
  951.  
  952.     case CLI$_PRESENT :
  953.         return(1);
  954.     case CLI$_ABSENT:
  955.         return(0);
  956.     case CLI$_NEGATED:
  957.         return(-1);
  958.         default:
  959.         return(0);
  960.     }    
  961. }
  962. /*
  963.  * **-vms_GetVal-Get Qualifier Value.
  964.  *
  965.  * Functional Description:
  966.  *
  967.  * This procedure is invoked to return the value associated with a
  968.  * qualifier that exists (See TstOpt).
  969.  */
  970. vms_GetVal( char opt, char *resval, unsigned short maxsiz)
  971. /*
  972.  * Arguments:
  973.  *
  974.  *  opt        Character label of qualifier to test for.
  975.  *  resval  Pointer to resulting value string.
  976.  *  maxsiz  Maximum size of string.
  977.  *
  978.  * Returns:
  979.  *
  980.  *  ...TBS...
  981.  *
  982.  * Implicit Inputs:
  983.  *
  984.  * Uses DCL command line context established by vms_GetOpt.
  985.  */
  986. {
  987.     int sts;
  988.     char buf;
  989.     struct dsc$descriptor option_d = { 1, 0, 0, &buf};
  990.     struct dsc$descriptor value_d = {maxsiz-1, 0, 0, resval };
  991.     unsigned short valsiz;
  992.  
  993.     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions to return */
  994.     buf = _toupper(opt);
  995.     if ((sts = cli$get_value( 
  996.         &option_d,
  997.         &value_d,
  998.         &valsiz)) & 01) resval[valsiz] = '\0';
  999.     return(sts);
  1000. }
  1001. /*
  1002.  * **-vms_GetArg-Get Argument Value.
  1003.  *
  1004.  * Functional Description:
  1005.  *
  1006.  * This procedure is invoked to return the value associated with an
  1007.  * argument.
  1008.  */
  1009. vms_GetArg( unsigned short arg, char *resval, unsigned short maxsiz)
  1010. /*
  1011.  * Arguments:
  1012.  *
  1013.  *  arg        Argument Number (1-9)
  1014.  *  resval  Pointer to resulting value string.
  1015.  *  maxsiz  Maximum size of string.
  1016.  *
  1017.  * Returns:
  1018.  *
  1019.  *  ...TBS...
  1020.  *
  1021.  * Implicit Inputs:
  1022.  *
  1023.  * Uses DCL command line context established by vms_GetOpt.
  1024.  */
  1025. {
  1026.     int sts;
  1027.     char buf[2] = "P";
  1028.     struct dsc$descriptor option_d = { 2, 0, 0, buf};
  1029.     struct dsc$descriptor value_d = {maxsiz-1, 0, 0, resval };
  1030.     unsigned short valsiz;
  1031.  
  1032.     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions to return */
  1033.     buf[1] = arg + '0';
  1034.     if ((sts = cli$present(&option_d)) & 01) {
  1035.     if ((sts = cli$get_value( 
  1036.         &option_d,
  1037.         &value_d,
  1038.         &valsiz)) & 01) resval[valsiz] = '\0';
  1039.     } else return(0);
  1040.     return(sts);
  1041. }
  1042.  
  1043.  
  1044.  
  1045. /*
  1046.  * **-do_help-Invoke VMS Help Processor
  1047.  *
  1048.  * Functional Description:
  1049.  *
  1050.  * This procedure is invoked to display a suitable help message to the caller
  1051.  * using the standard VMS help library.
  1052.  *
  1053.  */
  1054. do_help(char *helptext, char *helplib)
  1055. /*
  1056.  * Arguments:
  1057.  *
  1058.  *  helptext    Text of help request.
  1059.  *  helplib    Help library.
  1060.  *
  1061.  * Returns:
  1062.  *
  1063.  * As for kbhit_Getchn and lbr$output_help.
  1064.  *
  1065.  * Side Effects:
  1066.  *
  1067.  * A channel may be opened to the terminal. A library is opened.
  1068.  */
  1069. {
  1070.     int sts;
  1071.     int helpflags;
  1072.     struct dsc$descriptor helptext_d = { strlen(helptext), 0, 0, helptext};
  1073.     struct dsc$descriptor helplib_d = { strlen(helplib), 0, 0, helplib};
  1074.  
  1075.     VAXC$ESTABLISH(lib$sig_to_ret);   /*  Force unhandled exceptions to return */
  1076.     if (((sts = kbhit_Getchn()) & 01) || sts == 0) {
  1077.     helpflags = HLP$M_PROMPT|HLP$M_SYSTEM|HLP$M_GROUP|HLP$M_PROCESS;    
  1078.     sts = lbr$output_help(
  1079.             lib$put_output,
  1080.             &OldCharBuf.BufferSize,
  1081.             &helptext_d,
  1082.             &helplib_d,
  1083.             &helpflags,
  1084.             lib$get_input);
  1085.     }
  1086.     return(sts);
  1087. }
  1088. #endif /* _USEDCL_ */
  1089. unsigned long    vms_clock_bits[2];    /* VMS Hardware Clock */
  1090. const long    vms_ticks_per_update = 100000L; /* Clock update int. */
  1091.  
  1092. /*
  1093.  * FDL Stuff For Getting & Setting File Characteristics
  1094.  * This code was derived (loosely!) from the module LZVIO.C in the public 
  1095.  * domain LZW compress routine as found on the DECUS VAX SIG tapes (no author
  1096.  * given, so no credits!) 
  1097.  */
  1098.  
  1099. /*
  1100.  * **-fdl_generate-Generate An FDL
  1101.  *
  1102.  * Description:
  1103.  *
  1104.  * This procedure takes the name of an existing file as input and creates
  1105.  * an fdl. The FDL is retuned by pointer and length. The FDL space should be
  1106.  * released after use with a call to free();
  1107.  */
  1108. int fdl_generate(char *in_file, char **fdl, short *len)
  1109. /*
  1110.  * Arguments:
  1111.  *
  1112.  *    in_file        char*   Filename of file to examine (Zero terminated).
  1113.  *
  1114.  *    fdl        char*   Pointer to FDL that was created.
  1115.  *
  1116.  *    len        short   Length of FDL created.
  1117.  *
  1118.  * Status Returns:
  1119.  *
  1120.  * VMS style. lower bit set means success.
  1121.  */
  1122. {
  1123.  
  1124.     struct dsc$descriptor fdl_descr = { 0,
  1125.                 DSC$K_DTYPE_T,
  1126.                 DSC$K_CLASS_D,
  1127.                 0};
  1128.     struct FAB fab, *fab_addr;
  1129.     struct RAB rab, *rab_addr;
  1130.     struct NAM nam;
  1131.     struct XABFHC xab;
  1132.     int sts;
  1133.     int badblk;
  1134.  
  1135. /*
  1136.  * Build FDL Descriptor
  1137.  */
  1138.     if (!(sts = str$get1_dx(&FDLSIZE,&fdl_descr)) & 01) return(0);
  1139. /*
  1140.  * Build RMS Data Structures
  1141.  */
  1142.     fab = cc$rms_fab;
  1143.     fab_addr = &fab;
  1144.     nam = cc$rms_nam;
  1145.     rab = cc$rms_rab;
  1146.     rab_addr = &rab;
  1147.     xab = cc$rms_xabfhc;
  1148.     fab.fab$l_nam = &nam;
  1149.     fab.fab$l_xab = &xab;
  1150.     fab.fab$l_fna = in_file;
  1151.     fab.fab$b_fns = strlen(in_file);
  1152.     rab.rab$l_fab = &fab;
  1153.     fab.fab$b_fac = FAB$M_GET | FAB$M_BIO; /* This open block mode only */
  1154. /*
  1155.  * Attempt to Open File
  1156.  */
  1157.     if (!((sts = sys$open(&fab)) & 01)) {
  1158.     if (verbose) {
  1159.         fprintf(stderr,"\n(SYSTEM) Failed to $OPEN %s\n",in_file);
  1160.         (void) lib$signal(fab.fab$l_sts,fab.fab$l_stv);
  1161.     }
  1162.     return(sts);
  1163.     }
  1164.     if (fab.fab$l_dev & DEV$M_REC) {
  1165.     fprintf(stderr,"\n(SYSTEM) Attempt to read from output only device\n");
  1166.     sts = 0;
  1167.     } else {
  1168.     rab.rab$l_rop = RAB$M_BIO;
  1169.     if (!((sts = sys$connect(&rab)) & 01)) {
  1170.         if (verbose) {
  1171.         fprintf(stderr,"\n(SYSTEM) Failed to $CONNECT %s\n",in_file);
  1172.         (void) lib$signal(fab.fab$l_sts,fab.fab$l_stv);
  1173.         }
  1174.     } else {
  1175.         if (!((sts = fdl$generate(
  1176.             &flags,
  1177.             &fab_addr,
  1178.             &rab_addr,
  1179.             NULL,NULL,
  1180.             &fdl_descr,
  1181.             &badblk,
  1182.             len)) & 01)) {
  1183.         if (verbose)
  1184.             fprintf(stderr,"\n(SYSTEM) Failed to generate FDL\n",in_file);
  1185.         free(fdl);
  1186.         } else {
  1187.         if (!(*fdl = malloc(*len))) return(0);
  1188.         memcpy(*fdl,fdl_descr.dsc$a_pointer,*len);
  1189.         }
  1190.         (void) str$free1_dx(&fdl_descr);
  1191.     }
  1192.         sys$close(&fab);
  1193.     }
  1194.     return(sts);        
  1195. }
  1196.  
  1197. /*      
  1198.  * **-fdl_close-Closes files created by fdl_generate
  1199.  *  
  1200.  * Description:
  1201.  *
  1202.  * This procedure is invoked to close the file and release the data structures
  1203.  * allocated by fdl$parse.
  1204.  */
  1205. void fdl_close(void* rab)
  1206. /*
  1207.  * Arguments:
  1208.  *
  1209.  *    rab    VOID *    Pointer to RAB (voided to avoid problems for caller).
  1210.  *
  1211.  * Returns:
  1212.  *
  1213.  *    None.
  1214.  */
  1215. {
  1216.     struct FAB *fab;
  1217.  
  1218.     fab = ((struct RAB *) rab)->rab$l_fab;
  1219.     if (fab) {  /*  Close file if not already closed */
  1220.     if (fab->fab$w_ifi) sys$close(fab);
  1221.     }
  1222.     fdl$release( NULL, &rab);      
  1223. }
  1224.  
  1225. /*
  1226.  * **-fdl_create-Create A File Using the recorded FDL (hope we get it right!)
  1227.  *
  1228.  * Description:
  1229.  *
  1230.  * This procedure accepts an FDL and uses it create a file. Unfortunately
  1231.  * there is no way we can easily patch into the back of the VAX C I/O
  1232.  * subsystem.
  1233.  */
  1234. VOID * fdl_create( char *fdl, short len, char *outfile, char *preserved_name)
  1235. /*
  1236.  * Arguments:
  1237.  *
  1238.  *    fdl    char*    FDL string descriptor.
  1239.  *
  1240.  *    len    short    Returned string length.
  1241.  *
  1242.  *    outfile    char*    Output filename.
  1243.  *
  1244.  *    preserved_name char*    Name from FDL.
  1245.  *
  1246.  * Returns:
  1247.  *
  1248.  *     0 in case of error, or otherwise the RAB pointer.
  1249.  */
  1250. {
  1251.     VOID *sts;
  1252.     int sts2;
  1253.     struct FAB *fab;
  1254.     struct RAB *rab;
  1255.     struct NAM nam;
  1256.     int badblk;
  1257.     char *resnam;
  1258.  
  1259.     struct dsc$descriptor fdl_descr = {
  1260.                 len,
  1261.                 DSC$K_DTYPE_T,
  1262.                 DSC$K_CLASS_S,
  1263.                 fdl
  1264.                 };
  1265.  
  1266.     sts = NULL;
  1267. /*
  1268.  * Initialize RMS NAM Block
  1269.  */
  1270.     nam = cc$rms_nam;
  1271.     nam.nam$b_rss = NAM$C_MAXRSSLCL;
  1272.     nam.nam$b_ess = NAM$C_MAXRSSLCL;
  1273.     if (!(resnam = nam.nam$l_esa = malloc(NAM$C_MAXRSSLCL+1))) {
  1274.     fprintf(stderr,"\n(FDL_CREATE) Out of memory!\n");
  1275.     return(NULL);
  1276.     }
  1277. /*
  1278.  * Parse FDL
  1279.  */
  1280.     if (!((sts2 = fdl$parse( &fdl_descr,
  1281.                 &fab,
  1282.                 &rab,
  1283.                 &flags)) & 01)) {
  1284.     fprintf(stderr,"\nCreating (fdl$parse)\n");
  1285.     (void) lib$signal(sts2);
  1286.     } else {
  1287. /*
  1288.  * Extract & Return Name of FDL Supplied Filename
  1289.  */
  1290.     memcpy (preserved_name,fab->fab$l_fna,fab->fab$b_fns);
  1291.     preserved_name[fab->fab$b_fns] = '\0';
  1292. /*
  1293.  * Set Name Of Temporary File
  1294.  */
  1295.     fab->fab$l_fna = outfile;
  1296.     fab->fab$b_fns = strlen(outfile);
  1297. /*
  1298.  * Connect NAM Block
  1299.  */
  1300.     fab->fab$l_nam = &nam;
  1301.     fab->fab$l_fop |= FAB$M_NAM | FAB$M_CIF;
  1302.     fab->fab$b_fac |= FAB$M_BIO | FAB$M_PUT;
  1303. /*
  1304.  * Create File
  1305.  */
  1306.     if (!(sys$create(fab) & 01)) {
  1307.         fprintf(stderr,"\nCreating (RMS)\n");
  1308.         (void) lib$signal(fab->fab$l_sts,fab->fab$l_stv);
  1309.         fdl_close(rab);
  1310.     } else {
  1311.         if (verbose) {
  1312.         resnam[nam.nam$b_esl+1] = '\0';
  1313.         fprintf(stderr,"\nCreated %s successfully\n",resnam);
  1314.         }
  1315.         rab->rab$l_rop = RAB$M_BIO;
  1316.         if (!(sys$connect(rab) & 01)) {
  1317.         fprintf(stderr,"\nConnecting (RMS)\n");
  1318.         (void) lib$signal(rab->rab$l_sts,rab->rab$l_stv);
  1319.         fdl_close(rab);
  1320.         } else sts = rab;
  1321.     }
  1322.     fab->fab$l_nam = 0; /* I allocated NAM block, so I must deallocate it! */
  1323.     }
  1324.     free(resnam);
  1325.     return(sts);        
  1326. }
  1327.  
  1328. /*
  1329.  * **-fdl_copyfile2bin-Copies the input file to a 'binary' output file
  1330.  *
  1331.  * Description:
  1332.  *
  1333.  * This procedure is invoked to copy from an opened file f to a file opened
  1334.  * directly through RMS. This allows us to make a block copy into one of the
  1335.  * many esoteric RMS file types thus preserving characteristics without blowing
  1336.  * up the C RTL. This code is based directly on copyfile from FILEIO.C.
  1337.  *
  1338.  * Calling Sequence:
  1339.  */
  1340. int fdl_copyfile2bin( FILE *f, VOID *rab, word32 longcount)
  1341. /*
  1342.  * Arguments:
  1343.  *
  1344.  *    f        FILE*    Pointer to input file
  1345.  *
  1346.  *    rab        RAB*    Pointer to output file RAB
  1347.  * 
  1348.  *    longcount   word32    Size of file
  1349.  *
  1350.  * Returns:
  1351.  *
  1352.  *    0   If we were successful.
  1353.  *    -1  We had an error on the input file (VAXCRTL).
  1354.  *    +1  We had an error on the output file (direct RMS).
  1355.  */
  1356. {
  1357.     int status = 0;
  1358.     word32 count;
  1359.     ((struct RAB *) rab)->rab$l_rbf = &textbuf;
  1360.     ((struct RAB *) rab)->rab$l_bkt = 0;
  1361.     do { /*  Read and write longcount bytes */
  1362.     if (longcount < (word32) DISKBUFSIZE)
  1363.         count = longcount;
  1364.     else
  1365.         count = DISKBUFSIZE;
  1366.     count = fread(textbuf,1,count,f);
  1367.     if (count > 0) {
  1368. /*      
  1369.  *  No byte order conversion required, source and target system are both VMS so have
  1370.  *  the same byte ordering.
  1371.  */      
  1372.         ((struct RAB *) rab)->rab$w_rsz = (unsigned short) count;
  1373.         if (!(sys$write (
  1374.                rab, 
  1375.                NULL, 
  1376.                NULL) & 01)) {
  1377.           lib$signal(((struct RAB *) rab)->rab$l_sts,((struct RAB *) rab)->rab$l_stv);
  1378.           status = 1;
  1379.           break;
  1380.         }
  1381.         longcount -= count;
  1382.     }
  1383.     } while (count==DISKBUFSIZE);
  1384.     burn(textbuf);
  1385.     return(status);
  1386. }
  1387. /*
  1388.  * **-vms_fileparse-Parse A VMS File Specification
  1389.  *
  1390.  * Functional Description:
  1391.  *
  1392.  * This procedure is invoked to parse a VMS file specification using default 
  1393.  * and related specifications to fill in any missing components. This works a 
  1394.  * little like DCL's F$PARSE function with the syntax check only specified
  1395.  * (that is we don't check the device or the directory). The related file
  1396.  * spec is really for when we want to use the name of an input file (w/o the
  1397.  * directory) to supply the name of an output file.
  1398.  *
  1399.  * Note that we correctly handle the situation where the output buffer overlays
  1400.  * the input filespec by testing for the case and then handling it by copying
  1401.  * the primary input specification to a temporary buffer before parsing.
  1402.  */
  1403. int vms_fileparse( char *outbuf, char *filespec, char *defspec, char *relspec)
  1404. /*
  1405.  * Arguments:
  1406.  *
  1407.  *  outbuf    Returned file specification.
  1408.  *  filespec    Primary file specification (optional).
  1409.  *  defspec    Default file specification (optional).
  1410.  *  relspec    Related file specification (optional).
  1411.  *
  1412.  * Returns:
  1413.  *
  1414.  *  As for SYS$PARSE.
  1415.  *
  1416.  * Implicit Inputs:
  1417.  *
  1418.  *  None.
  1419.  *
  1420.  * Implicit Outputs:
  1421.  *
  1422.  *  None.
  1423.  *
  1424.  * Side Effects:
  1425.  *
  1426.  *  ...TBS...
  1427.  */
  1428. {
  1429.     struct FAB fab = cc$rms_fab;
  1430.     struct NAM nam = cc$rms_nam;
  1431.     struct NAM rlnam = cc$rms_nam;
  1432.     int sts = 1;
  1433.     int len;
  1434.     char tmpbuf[NAM$C_MAXRSSLCL];
  1435.     char expfnam2[NAM$C_MAXRSSLCL];
  1436.  
  1437.     if (outbuf != NULL) {
  1438.     outbuf[0] = '\0';
  1439.     fab.fab$l_fop != FAB$M_NAM;  /*  Enable RMS NAM block processing */
  1440.     nam.nam$b_nop |= NAM$M_PWD | NAM$M_SYNCHK;
  1441.     /*      
  1442.     **  Handle Related Spec (If reqd).
  1443.     */      
  1444.     if (relspec != NULL) {
  1445.         if ((len = strlen(relspec)) > 0) {
  1446.         fab.fab$l_nam = &rlnam;
  1447.         fab.fab$b_fns = len;
  1448.         fab.fab$l_fna = relspec;
  1449.         rlnam.nam$b_ess = NAM$C_MAXRSSLCL;
  1450.         rlnam.nam$l_esa = expfnam2;
  1451.         rlnam.nam$b_nop |= NAM$M_PWD | NAM$M_SYNCHK;
  1452.         if ((sts = sys$parse (
  1453.                 &fab, 
  1454.                 0, 
  1455.                 0)) & 01) {
  1456.             rlnam.nam$l_rsa = rlnam.nam$l_esa;
  1457.             rlnam.nam$b_rsl = rlnam.nam$b_esl;
  1458.             nam.nam$l_rlf = &rlnam;
  1459.             fab.fab$l_fop |= FAB$M_OFP;
  1460.         }
  1461.         }
  1462.     }
  1463.     if (sts) {
  1464.         fab.fab$l_nam = &nam;
  1465.         nam.nam$l_esa = outbuf;
  1466.         nam.nam$b_ess = NAM$C_MAXRSSLCL;
  1467.         /*      
  1468.         **  Process Default Specification:
  1469.         */      
  1470.         if (defspec != NULL) {
  1471.         if ((len = strlen(defspec)) > 0) {
  1472.             fab.fab$l_dna = defspec;
  1473.             fab.fab$b_dns = len;
  1474.         }
  1475.         }
  1476.         /*      
  1477.         **  Process Main File Specification:
  1478.         */      
  1479.         fab.fab$l_fna = NULL;
  1480.         fab.fab$b_fns = 0;
  1481.         if (filespec != NULL) {
  1482.         if ((len = strlen(filespec)) > 0) {
  1483.             fab.fab$b_fns = len;
  1484.             if (filespec == outbuf)
  1485.             fab.fab$l_fna = memcpy(tmpbuf,filespec,len);
  1486.             else
  1487.             fab.fab$l_fna = filespec;
  1488.         }
  1489.         }
  1490.         if ((sts = sys$parse(
  1491.                &fab, 
  1492.                0, 
  1493.                0)) && 01) outbuf[nam.nam$b_esl] = '\0';
  1494.     }
  1495.     }
  1496.     return (sts);
  1497. }
  1498. #endif /* VMS */
  1499.  
  1500.  
  1501. /*========================================================================*/
  1502. /*
  1503.  * AMIGA
  1504.  */
  1505.  
  1506. #ifdef AMIGA    /* Amiga-specific stuff */
  1507.  
  1508. #include <exec/types.h>
  1509. #include <exec/memory.h>
  1510. #include <exec/ports.h>
  1511. #include <libraries/dosextens.h>
  1512. #ifdef LATTICE
  1513. #include <proto/exec.h> 
  1514. #include <proto/dos.h> 
  1515. #endif /* LATTICE */
  1516. extern FILE *pgpout;
  1517. extern int aecho;
  1518.  
  1519.  
  1520. /* amiga version of getch() 
  1521.    Cor Bosman , jul-22-92 
  1522. */
  1523.  
  1524.  
  1525. sendpacket(struct MsgPort *rec,LONG action,LONG arg1) 
  1526. {
  1527.   struct StandardPacket *pkt;
  1528.   struct msgPort *rp;
  1529.   LONG res1 = 0L;
  1530.  
  1531.   if (rp = (struct MsgPort *)CreatePort(NULL,0L)) {
  1532.     if (pkt = (struct StandardPacket *)\
  1533.      AllocMem(sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR)) {
  1534.        pkt->sp_Msg.mn_Node.ln_Name = (BYTE *)&pkt->sp_Pkt;
  1535.        pkt->sp_Pkt.dp_Link = &pkt->sp_Msg;
  1536.        pkt->sp_Pkt.dp_Port = rp;
  1537.        pkt->sp_Pkt.dp_Type = action;
  1538.        pkt->sp_Pkt.dp_Arg1 = arg1;
  1539.        PutMsg(rec,&pkt->sp_Msg);
  1540.        WaitPort(rp);
  1541.        GetMsg(rp);
  1542.        res1 = pkt->sp_Pkt.dp_Res1;
  1543.        FreeMem((UBYTE*)pkt,sizeof(struct StandardPacket));
  1544.      }
  1545.      DeletePort(rp);
  1546.     }
  1547.     return(res1);
  1548.  
  1549. }
  1550.  
  1551. /* ttycbreak for amiga.
  1552.  * Cor Bosman , jul-30-92
  1553. */
  1554.  
  1555. void ttycbreak()
  1556. {
  1557.   BPTR in,out;
  1558.   char buf[128];
  1559.   struct MsgPort *ch;
  1560.  
  1561.   in=Input();
  1562.   out=Output();
  1563.   ch = ((struct FileHandle *)BADDR(in))->fh_Type;
  1564.   sendpacket(ch,ACTION_SCREEN_MODE,-1L);
  1565. }
  1566.  
  1567. /* ttynorm for amiga
  1568.  * Cor Bosman , jul-30-92
  1569. */
  1570.  
  1571. void ttynorm()
  1572. {
  1573.  
  1574.   BPTR in,out;
  1575.   char buf[128];
  1576.   struct MsgPort *ch;
  1577.  
  1578.   in=Input();
  1579.   out=Output();
  1580.   ch = ((struct FileHandle *)BADDR(in))->fh_Type;
  1581.   sendpacket(ch,ACTION_SCREEN_MODE,0L);
  1582. }
  1583.  
  1584. char getch(void)
  1585. {
  1586.   char buf[128];
  1587.   BPTR in,out;
  1588.  
  1589.   in = Input();
  1590.   out = Output();
  1591.   Read(in,buf,1);
  1592.   if (aecho) 
  1593.     Write(out, buf, 1);
  1594.   return(buf[0]);
  1595. }
  1596.  
  1597. /* kbhit() function for amiga.
  1598.  * Cor Bosman , jul-30-92
  1599. */
  1600.  
  1601. int kbhit() 
  1602. {
  1603.   if(WaitForChar(Input(), 1)) return 1;
  1604.   return 0;
  1605. }
  1606.  
  1607. #ifdef LATTICE
  1608.  
  1609. /*
  1610.  *  Lattice-C  ^C-Handler 
  1611. */
  1612.  
  1613. int CXBRK()
  1614. {
  1615.   BPTR in,out;
  1616.   struct MsgPort *ch;
  1617.   in=Input();
  1618.   out=Output();
  1619.  
  1620.   /* it might happen we catch a ^C while in cbreak mode.
  1621.    * so always set the screen to the normal mode.
  1622.   */
  1623.  
  1624.   ch = ((struct FileHandle *)BADDR(in))->fh_Type;
  1625.   sendpacket(ch, ACTION_SCREEN_MODE, 0L);
  1626.  
  1627.  
  1628.   fprintf(pgpout, "\n*** Program Aborted.\n");
  1629.   exitPGP(6); /* INTERRUPT */
  1630. }
  1631. #endif
  1632.  
  1633. /*------------------------------------------------------------------------
  1634.  * clock.c -- time in microseconds since first call of clock()
  1635.  *
  1636.  * RP: this function is missing from SAS/C library.
  1637.  */
  1638.  
  1639. #include <time.h>
  1640.  
  1641. long clock()
  1642. {
  1643.     static unsigned long oldms = -1;
  1644.     unsigned long cl[2],ms;
  1645.  
  1646.     timer(cl);
  1647.     ms = cl[0] * 1000000 + cl[1] % 1000000;
  1648.     if(oldms == -1) {
  1649.         oldms = ms;
  1650.         return 0;
  1651.     } else {
  1652.         return ((long)(ms-oldms));
  1653.     }
  1654. }
  1655.  
  1656.  
  1657. #endif /* AMIGA */
  1658.  
  1659.  
  1660.  
  1661. /*===========================================================================*/
  1662. /*
  1663.  * other stuff for non-MSDOS systems
  1664.  */
  1665.  
  1666. #ifdef ATARI
  1667. #include <string.h>
  1668. #endif
  1669.  
  1670. #if !defined(MSDOS) && !defined(ATARI)
  1671. #include <ctype.h>
  1672. #include "charset.h"
  1673. char *strlwr(char *s)
  1674. {    /*
  1675.     **        Turns string s into lower case.
  1676.     */
  1677.     int c;
  1678.     char *p = s;
  1679.     while (c = *p)
  1680.         *p++ = to_lower(c);
  1681.     return(s);
  1682. }
  1683. #endif /* !MSDOS && !ATARI */
  1684.  
  1685.  
  1686. #ifdef strstr
  1687. #undef strstr
  1688. /* Not implemented on some systems - return first instance of s2 in s1 */
  1689. char *mystrstr (char *s1, char *s2)
  1690. {    int i;
  1691.     char *strchr();
  1692.  
  1693.     if (!s2 || !*s2)
  1694.         return s1;
  1695.     for ( ; ; )
  1696.     {    if (!(s1 = strchr (s1, *s2)))
  1697.             return s1;
  1698.         for (i=1; s2[i] && (s1[i]==s2[i]); ++i)
  1699.             ;
  1700.         if (!s2[i])
  1701.             return s1;
  1702.         ++s1;
  1703.     }
  1704. }
  1705. #endif /* strstr */
  1706.  
  1707.  
  1708. #ifdef fopen
  1709. #undef fopen
  1710.  
  1711. #ifdef ATARI
  1712. #define F_BUF_SIZE 8192  /* seems to be a good value ... */
  1713.  
  1714. FILE *myfopen(const char *filename, const char *mode)
  1715. /* Open streams with larger buffer to increase disk I/O speed. */
  1716. /* Adjust F_BUF_SIZE to change buffer size.                    */
  1717. {
  1718.     FILE *f;
  1719.  
  1720.     if ( (f = fopen(filename, mode)) != NULL )
  1721.         if (setvbuf(f, NULL, _IOFBF, F_BUF_SIZE)) /* no memory? */
  1722.         {
  1723.             fclose(f);                 /* then close it again */
  1724.             f = fopen(filename, mode); /* and try again in normal mode */
  1725.         }
  1726.     return(f);                         /* return either handle or NULL */
  1727. }
  1728.     
  1729. #else /* ATARI */
  1730.  
  1731. /* Remove "b" from 2nd arg */
  1732. FILE *myfopen(char *filename, char *type)
  1733. {    char buf[10];
  1734.  
  1735.     buf[0] = *type++;
  1736.     if (*type=='b')
  1737.         ++type;
  1738.     strcpy(buf+1,type);
  1739.     return fopen(filename, buf);
  1740. }
  1741. #endif /* not ATARI */
  1742. #endif /* fopen */
  1743.  
  1744.  
  1745. #ifndef MSDOS
  1746. #ifdef OS2
  1747.  
  1748. static int chr = -1;
  1749.  
  1750. int kbhit(void)
  1751. {
  1752.     if (chr == -1)
  1753.           chr = _read_kbd(0, 0, 0);
  1754.     return (chr != -1);
  1755. }
  1756.  
  1757. int getch(void)
  1758. {
  1759.     int c;
  1760.  
  1761.     if (chr >= 0) {
  1762.         c = chr;
  1763.         chr = -1;
  1764.     } else
  1765.           c = _read_kbd(0, 1, 0);
  1766.  
  1767.     return c;
  1768. }
  1769.  
  1770. #endif /* OS2 */
  1771. #endif /* MSDOS */
  1772.